<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>17.箭头函数带来的this变化实例</title>
</head>

<body>
  <button desc="hdcms">button</button>
  <button desc="houdunren">button</button>
  <script>

    //箭头函数没有this, 也可以理解为箭头函数中的this 会继承定义函数时的上下文，可以理解为和外层函数指向同一个 this。
    // 如果想使用函数定义时的上下文中的 this，那就使用箭头函数

    // 下例中的匿名函数的执行环境为全局所以 this 指向 window。
    var name = 'hdcms';
    var obj = {
      name: '后盾人',
      getName: function () {
        return function () {
          return this.name;
        }
      }
    }
    console.log(obj.getName()()); //返回window.name的值hdcms

    // 以往解决办法会匿名函数调用处理定义变量，然后在匿名函数中使用。
    var name = 'hdcms';
    var obj = {
      name: '后盾人',
      getName: function () {
        var self = this;
        return () => {
          return self.name;
        }
      }
    }
    console.log(obj.getName()()); //返回window.name的值hdcms
    //使用箭头函数后 this 为定义该函数的上下文，也可以理解为定义时父作用域中的this
    var name = 'hdcms';
    var obj = {
      name: '后盾人',
      getName: function () {
        return () => {
          return this.name;
        }
      }
    }
    console.log(obj.getName()()); //后盾人
    // 当我们既想使用对象内的属性，又想用Dom对象的属性时，可以使用箭头函数改变this的指向
    // 使用普通函数时this为当前 DOM 对象
    let Dom = {
      site: "后盾人",
      bind () {
        const button = document.querySelector("button");
        button.addEventListener("click", function () {
          alert(this.getAttribute("desc"));
        });
      }
    };
    Dom.bind();
    Dom = {
      site: "后盾人",
      bind () {
        const button = document.querySelector("button");
        button.addEventListener("click", event => {
          alert(this.site + event.target.innerHTML);
        });
      }
    };
    Dom.bind();
    // 使用handlerEvent可以处理点击事件
    // 使用handleEvent绑定事件处理器时，this指向当前对象而不是 DOM 元素。
    Dom = {
      site: "后盾人",
      handleEvent: function (event) {
        console.log(this);
      },
      bind () {
        const button = document.querySelector("button");
        button.addEventListener("click", this);
      }
    };
    Dom.bind();
    // 面对多层嵌套使用箭头函数，要考虑上层的this指向
    Dom = {
      site: "后盾人",
      handleEvent: function (event) {
        console.log(this.site + event.target.innerHTML);
      },
      bind: function () {
        let buttons = document.querySelectorAll("button");
        buttons.forEach( elem =>{ 
          // 本层使用了箭头函数， this 指向了对象
          elem.addEventListener('click',this);
        });
      }
    };
    Dom.bind();
  </script>
</body>

</html>